package com.king.common.utils.file;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;

import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;

import com.king.framework.config.ProjectConfig;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;

import com.king.common.constant.Constants;
import com.king.common.utils.text.StringUtils;

/**
 * 图片处理工具类
 *
 * @author king
 */
public class ImageUtils {
	private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);



    //进行压缩的最小大小：100KB
    public static final int THUM_MIN_SIZE = 1024 * 100;
    //1MB
    public static final int M_BYTE = 1024 * 1024;
    // 支持压缩的图片类型文件后缀
    public final static List<String> imgSuffix = Arrays.asList("bmp", "jpg", "jpeg", "png", "tif", "gif", "pcx", "tga", "exif", "fpx", "svg", "psd", "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "wmf", "webp");
    private final static String jpg = "jpg";
    private final static String jpeg = "jpeg";
    
	
	public static byte[] getImage(String imagePath) {
		InputStream is = getFile(imagePath);
		try {
			return IOUtils.toByteArray(is);
		} catch (Exception e) {
			log.error("图片加载异常 {}", e);
			return null;
		} finally {
			IOUtils.closeQuietly(is);
		}
	}

	public static InputStream getFile(String imagePath) {
		try {
			byte[] result = readFile(imagePath);
			result = Arrays.copyOf(result, result.length);
			return new ByteArrayInputStream(result);
		} catch (Exception e) {
			log.error("获取图片异常 {}", e);
		}
		return null;
	}

	/**
	 * 读取文件为字节数据
	 * 
	 * @param url
	 *            地址
	 * @return 字节数据
	 */
	public static byte[] readFile(String url) {
		InputStream in = null;
		try {
			if (url.startsWith("http")) {
				// 网络地址
				URL urlObj = new URL(url);
				URLConnection urlConnection = urlObj.openConnection();
				urlConnection.setConnectTimeout(30 * 1000);
				urlConnection.setReadTimeout(60 * 1000);
				urlConnection.setDoInput(true);
				in = urlConnection.getInputStream();
			} else {
				// 本机地址
				String localPath = ProjectConfig.getProfile();
				String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
				in = new FileInputStream(downloadPath);
			}
			return IOUtils.toByteArray(in);
		} catch (Exception e) {
			log.error("获取文件路径异常 {}", e);
			return null;
		} finally {
			IOUtils.closeQuietly(in);
		}
	}
	
	
	  /**
     * 给图片添加水印
     *
     * @param imgPath          原图路径
     * @param watermarkImgPath
     * @param positions
     * @param opacity          透明度 0-1.0f
     * @return 返回添加水印后的图片路径
     * @throws IOException
     */
    public static String watermark(String imgPath, String watermarkImgPath, Positions positions, float opacity) throws IOException {
        // 获取添加水印后的图片路径
        String resultPath = getWatermarkImgPath(imgPath);
        BufferedImage watermarkImage = ImageIO.read(new File(watermarkImgPath));
        Thumbnails.of(imgPath)
                .size(100, 100)
                .watermark(positions, watermarkImage, opacity)
                .toFile(new File(resultPath));
        return resultPath;
    }

    /**
     * 压缩图片，压缩后的图片路径  格式如： 1.jpg -> 1-reduce.jpg
     *
     * @param originalFile 原图片文件
     * @return JPG原图的绝对路径
     */
    public static String reduceImage(File originalFile) throws IOException {
        if (originalFile == null || !originalFile.exists()) {
            throw new IllegalArgumentException("文件不存在");
        }
        //原图绝对路径
        String originalAbsPath = originalFile.getAbsolutePath();
        //jpg原图路径
        String jpgFilePath = originalAbsPath;
        //获取文件类型后缀
        String suffix = getFileSuffix(jpgFilePath);
        if (!isImage(suffix)) {
            //不支持的文件类型，返回原图路径
            return originalAbsPath;
        }
        //true表示是jpg文件
        boolean isJpg = isJpg(suffix);
        if (!isJpg) {
            //如果不是jpg格式的图片，转为jpg
            jpgFilePath = getJpgPath(jpgFilePath);
            //转换为jpg格式后的文件
            File jpgFile = new File(jpgFilePath);
            conversion(originalFile, jpgFile);
            originalFile = jpgFile;
        }
        // 获取压缩图片的路径
        String reduceImgPath = getReduceImgPath(jpgFilePath);
        // 压缩的质量，1代表保持原有的质量(默认1) 范围 1-0
        float quality = getQuality(originalFile);
        if (quality == 1.0f) {
            // 原图片小于最小压缩大小 不做压缩
            FileCopyUtils.copy(originalFile, new File(reduceImgPath));
        } else {
            //进行压缩
            Thumbnails.of(jpgFilePath).scale(1f).outputQuality(quality).toFile(reduceImgPath);
        }
        return originalAbsPath;
    }

    /**
     * true表示是jpg文件
     *
     * @param suffix
     * @return
     */
    public static boolean isJpg(String suffix) {
        boolean isJpg = jpg.equalsIgnoreCase(suffix) || jpeg.equalsIgnoreCase(suffix);
        return isJpg;
    }

    /***
     * true表示是图片文件
     * @param suffix
     * @return
     */
    public static boolean isImage(String suffix) {
        for (String type : imgSuffix) {
            if (type.equalsIgnoreCase(suffix))
                return true;
        }
        return false;
    }

    /**
     * 获取压缩的质量
     *
     * @param originalFile
     * @return
     */
    private static float getQuality(File originalFile) {
        // jpg原图大小
        long fileSize = originalFile.length();
        // 压缩的质量，1代表保持原有的质量(默认1) 范围 1-0
        float quality = 1.0f;
        if (fileSize <= THUM_MIN_SIZE) {
            // 原图片小于最小压缩大小 不做压缩
            quality = 1.0f;
        } else if (fileSize <= M_BYTE) {
            // 小于1MB
            quality = (THUM_MIN_SIZE * 1.0f) / fileSize;
        } else if (fileSize <= M_BYTE * 5) {
            // 大于1000K 都按0.1比例压缩
            quality = 0.1f;
        }
        return quality;
    }


    /**
     * 获取压缩图片的路径
     *
     * @param filePath 原图路径
     * @return
     */
    public static String getReduceImgPath(String filePath) {
        // 获取除了文件类型后缀外的路径
        String path = getFilePathExceptSuffix(filePath);
        return StringUtils.format("{}-reduce.{}", path, jpg);
    }

    /**
     * 获取水印图片的绝对路径
     *
     * @param filePath 文件路径
     * @return
     */
    private static String getWatermarkImgPath(String filePath) {
        // 获取除了文件类型后缀外的路径
        String path = getFilePathExceptSuffix(filePath);
        //获取文件类型后缀
        String suffix = getFileSuffix(filePath);
        return StringUtils.format("{}-watermark.{}", path, suffix);
    }

    /**
     * 获取除了文件类型后缀外的路径
     *
     * @param filePath 文件路径
     * @return
     */
    public static String getFilePathExceptSuffix(String filePath) {
        return StringUtils.substringBeforeLast(filePath, ".");
    }

    /**
     * 获取文件类型后缀
     *
     * @param filePath 文件路径
     * @return
     */
    public static String getFileSuffix(String filePath) {
        //获取文件类型后缀
        return StringUtils.substringAfterLast(filePath, ".").toLowerCase();
    }

    /**
     * 获取转为jpg后的图片路径
     *
     * @param filePath 原图路径
     * @return
     */
    private static String getJpgPath(String filePath) {
        // 获取除了文件类型后缀外的路径
        String path = getFilePathExceptSuffix(filePath);
        return StringUtils.format("{}.{}", path, jpg);
    }

    /**
     * 图片格式转换
     *
     * @param input  原图片文件
     * @param output 转换后的图片文件
     */
    public static void conversion(File input, File output) throws IOException {
        BufferedImage bi = ImageIO.read(input);
        BufferedImage newBufferedImage = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_RGB);
        newBufferedImage.createGraphics().drawImage(bi, 0, 0, Color.WHITE, null);
        ImageIO.write(newBufferedImage, jpg, output);
    }

}
